##############################################################################
#
# CiscoRouter.pm
# =================
#
# Author: Steven Liang <stliang@gmail.com>
#
# Purpose:
#   Parent class of Cisco router types
#   CiscoRouter.pm is a child of Node.
#
# Assumptions:
#   1.) 
#
# Supported methods:
#   All Node's methods plus
#   new($ip, $userName, $passWord, $enablePassWord ; $port || 23);
#   getEnablePassWord();
#   showIPRoute();
#
# Note:
#   Variable after ";" is optional variable and value after "||" is 
#   default value
#
##############################################################################

package CiscoRouter;
$VERSION = 1.01;

@ISA = qw(Node); # The @ISA array supports multiple inheritance
		 # For single parent use "use base" key word.

use strict;
use AutoTest::Exceptions;

# Constructor: new
# Purpose:     Instantiate a CiscoRouter object
# Parameters:
#       1.) ip : IP address of the node
#       2.) userName : User name used for login
#       3.) passWord : Password used for login
#       4.) enablePassWord : Enable password used for admin access
#       5.) port : A port to use for telnet, default value is 23
#
# Returns:    An instance of Network::C2500 class
#
sub new ($$$$;$) {
	my $class = shift;
	my $self = { };
	if (defined($_[4])) {
		$self = Node->new($_[0], $_[1], $_[2], $_[4]);
	} else {
		$self = Node->new($_[0], $_[1], $_[2]);
	}
	bless $self, $class;
	$self->{"enablePassWord"} = $_[3];
	return $self;
}

# Method:     getEnablePassWord
# Purpose:    Read the value of enablePassWord
# Parameters: None
# Returns:    enablePassWord
sub getEnablePassWord () {
	my $self = shift;
	return $self->{"enablePassWord"};
}

# Method:     login
# Purpose:    Login to Cisco router and establish enabled mode
# Parameters:
#             1.) userNamePrompt: The user name prompt
#             2.) passWordPrompt: The password prompt
#             3.) userPrompt: User prompt after successful login
#             4.) enablePrompt: Enable prompt after successful switch to enabled mode
#             5.) timeout: Optional timeout value
#
# Returns:    Void
sub login ($$$;$) {
        my ($self) = shift;
        my ($userNamePrompt) = shift;
        my ($passWordPrompt) = shift;
        my ($userPrompt) = shift;
        my ($enablePrompt) = shift;
        my ($timeout) = defined($_[0]) ? shift : 60;
	$self->expectTimeout($timeout);
        my $spawn_ok;
	if (defined($userNamePrompt)) {
	$self->{exp}->expect($self->expectTimeout(),
                [
                $userNamePrompt,
                sub {
                        $spawn_ok = 1;
                        $self->{exp}->send("$self->{userName}\n");
                    }
                ],
		[
                eof =>
                sub {
                        if ($spawn_ok) {
				AutoTest::Exception::Expect->throw("premature EOF in login");
                        # die "ERROR: premature EOF in login.\n";
                        } else {
				AutoTest::Exception::Connection->throw('could not spawn telnet @ loginPrompt detection');
                        # die "ERROR: could not spawn telnet @ loginPrompt detection.\n";
                        }
                    }
                ],
                [
                	timeout =>
                	sub {
				AutoTest::Exception::Expect->throw("timeout expecting user name prompt");
                        	# die "No user name prompt.\n";
                	}
                ]
	);
	}

	$self->{exp}->expect($self->expectTimeout(),
                [
                	$passWordPrompt,
                	sub {
                        	$spawn_ok = 1;
                        	$self->{exp}->send("$self->{passWord}\n");
                   	 }
                ],
		[
                eof =>
                sub {
                        if ($spawn_ok) {
			AutoTest::Exception::Expect->throw("premature EOF in login");
                        # die "ERROR: premature EOF in login.\n";
                        } else {
			AutoTest::Exception::Connection->throw('could not spawn telnet @ passWordPrompt detection');
                        # die "ERROR: could not spawn telnet @ passWordPrompt detection.\n";
                        }
                    }
                ],
                [
                	timeout =>
                	sub {
				AutoTest::Exception::Expect->throw("timeout expecting user name prompt");
                        	# die "No pass word prompt.\n";
                	}
                ]
	);

	$self->{exp}->expect($self->expectTimeout(),
                [
                	$userPrompt,
                	sub {
				$self->cmdPrompt($userPrompt);
                        	$self->{exp}->send("enable\n");
                   	 }
                ],
                [
                	timeout =>
                	sub {
				AutoTest::Exception::Expect->throw("Timeout expecting user prompt");
                        	# die "No user prompt.\n";
                	}
                ]
	);

	$self->{exp}->expect($self->expectTimeout(),
                [
                	$passWordPrompt,
                	sub {
                        	$self->{exp}->send("$self->{enablePassWord}\n");
                   	 }
                ],
                [
                	timeout =>
                	sub {
				AutoTest::Exception::Expect->throw("Timeout expecting enable password prompt");
                        	# die "No password prompt.\n";
                	}
                ]
	);

	$self->{exp}->expect($self->expectTimeout(),
                [
                	$enablePrompt,
                	sub {
				$self->cmdPrompt($enablePrompt);
                        	# $self->{exp}->send("");
                   	 }
                ],
                [
                	timeout =>
                	sub {
				AutoTest::Exception::Expect->throw("Timeout expecting enable prompt");
                        	# die "No enable prompt.\n";
                	}
                ]
	);
}

# Method:     showIPRoute
# Purpose:    Execute Cisco's show ip route command
# Parameters: None
# Returns:    Show ip route command output
sub showIPRoute () {
	my $self = shift;
	$self->send("show ip route\n");
        return $self->getOutPut();
}
